package me.xplabs.engine.time 
{
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	/**
	 * ...
	 * @author xiaohan
	 */
	public class TimeManager 
	{
		public var now:int;
		//自 1970 年 1 月 1 日午夜（通用时间）以来的毫秒数。
		public var time:Number;
		public var gap:int;
		public var delay:Number;
		public var curFrame:int;
		private var _prev:int;
		private var _gaps:Dictionary;
		//延迟到下一帧处理
		private var _delayFrameFuncs:Vector.<Function>;
		private var _nextGapIndex:int;
		//一秒计时的cd时间
		private var _cdFuncs:Dictionary;
		private var _cdGap:TimeGapNode;
		private var _initTime:Number;
		private var _startTime:Number;
		private var _nextUpdateIndex:int;
		private var _updateFuncs:Dictionary;
		
		public var date:Date;
		
		private var _timePieces:Dictionary;
		private var _nextPieceIndex:int;
		public function TimeManager() 
		{
			date = new Date();
			now = getTimer();
			time = (new Date()).time;
			_initTime = now;
			_startTime = time;
			
			_gaps = new Dictionary();
			_timePieces = new Dictionary();
			_cdFuncs = new Dictionary();
			_updateFuncs = new Dictionary();
			_delayFrameFuncs = new Vector.<Function>();
			_cdGap = new TimeGapNode(0, now, .5, updateCd, null, -1, false);
		}
		/**
		 * 添加帧频刷新函数
		 * @param	func
		 * @return
		 */
		public function addUpdate(func:Function):int 
		{
			_nextUpdateIndex++;
			_updateFuncs[_nextUpdateIndex] = new TimeUpdateNode(_nextUpdateIndex, { update:func } );
			return _nextUpdateIndex;
		}
		/**
		 * 移除帧频刷新函数
		 * @param	pkey
		 */
		public function removeUpdate(pkey:int):void
		{
			if (_updateFuncs[pkey] == null) return;
			delete _updateFuncs[pkey];
			if (pkey == _nextUpdateIndex) 
			{
				_nextUpdateIndex--;
				while (_updateFuncs[_nextUpdateIndex] == null)
				{
					if (_nextUpdateIndex == 0) return;
					_nextUpdateIndex--;
				}
			}
		}
	   /**
		* 添加对象的计时效果
		* @param	obj
		* @param	duration
		* @param	pars
		* @return
		*/
	   public function to(obj:Object, duration:Number, pars:Object):int 
	   {
		   _nextUpdateIndex++;
		   _updateFuncs[_nextUpdateIndex] = new TimeUpdateNode(_nextUpdateIndex, pars, duration, obj);
		   return _nextUpdateIndex;
	   }
	   /**
	    * 添加计时器
	    * @param	pgap 计时间隔时间
	    * @param	func 计时回调函数
	    * @param	ptimes 计时总次数
	    * @param	endFunc 计时结束回调函数
	    * @param	isJumpPer
	    * @return
	    */
		public function addGap(pgap:Number, func:Function, ptimes:int = -1, endFunc:Function = null, isJumpPer:Boolean = true):int
		{
			_nextGapIndex++;
			_gaps[_nextGapIndex] = new TimeGapNode(_nextGapIndex, now, pgap, func, endFunc, ptimes, isJumpPer);
			return _nextGapIndex;
		}
		/**
		 * 移除计时器
		 * @param	pkey
		 */
		public function removeGap(pkey:int):void
		{
			if (_gaps[pkey] == null) return;
			var p:* = _gaps[pkey];
			delete _gaps[pkey];
			if (p.dispose != undefined) p.dispose();
			
			if (pkey == _nextGapIndex) 
			{
				_nextGapIndex--;
				while (_gaps[_nextGapIndex] == null)
				{
					if (_nextGapIndex == 0) break;
					_nextGapIndex--;
				}
			}
		}
		/**
		 * 添加计时器
		 * @param	pgap
		 * @param	func
		 * @param	ptimes
		 * @param	endFunc
		 * @return
		 */
		public function addTimePiece(pgap:Number, func:Function, ptimes:int = -1, endFunc:Function = null):int
		{
			_nextPieceIndex++;
			_timePieces[_nextPieceIndex] = new TimePieceNode(_nextPieceIndex, now, pgap, func, endFunc, ptimes);
			return _nextPieceIndex;
		}
		public function removeTimePiece(pkey:int):void
		{
			if (_timePieces[pkey] == null) return;
			var p:* = _timePieces[pkey];
			delete _timePieces[pkey];
			if (p.dispose != undefined) p.dispose();
			
			if (pkey == _nextPieceIndex) 
			{
				_nextPieceIndex--;
				while (_timePieces[_nextPieceIndex] == null)
				{
					if (_nextPieceIndex == 0) break;
					_nextPieceIndex--;
				}
			}
		}
		/**
		 * 添加延迟计时器
		 * @param	ptime 计时时间
		 * @param	func 计时结束回调
		 * @return
		 */
		public function addDelay(ptime:Number, func:Function):int
		{
			return addGap(ptime, func, 1);
		}
		/**
		 * 添加cd时间计时器
		 * @param	pkey cd时间的key值
		 * @param	totalTime 计时总时间
		 * @param	updateFunc 计时刷新回调函数
		 * @param	endFunc 计时结束回调函数
		 */
		public function addCd(pkey:String, totalTime:int, updateFunc:Function, endFunc:Function = null):void
		{
			if (_cdFuncs[pkey] != null)
			{
				var o:Object = _cdFuncs[pkey];
				o.total = totalTime;
				o.update = updateFunc;
				o.end = endFunc;
				o.prev = now;
			} else {
				_cdFuncs[pkey] = {prev:now, total:totalTime, update:updateFunc, end:endFunc };
			}
		}
		/**
		 * 移除cd时间计时器
		 * @param	pkey
		 */
		public function removeCd(pkey:String):void
		{
			if (_cdFuncs[pkey] != null) delete _cdFuncs[pkey];
		}
		/**
		 * 刷新cd时间
		 */
		private function updateCd():void 
		{
			var pkey:String;
			for (pkey in _cdFuncs) 
			{
				var obj:Object = _cdFuncs[pkey];
				if (obj.prev > now) continue;
				obj.total--;
				obj.prev += 1000;
				if (obj.update != null)
					switch(obj.update.length) {
						case 0:
							obj.update();
							break;
						case 1:
							obj.update(obj.total);
							break;
						case 2:
							obj.update(pkey, obj.total);
							break;
					}
				if (obj.total <= 0) {
					if (obj.end != null) {
						if (obj.end.length == 0) obj.end();
						else obj.end(pkey);
					}
					removeCd(pkey);
				}
			}
		}
		public function update():void
		{
			now = getTimer();
			gap = now - _prev;
			_prev = now;
			time = _startTime + now - _initTime;
			
			//trace(gap);
			
			while (_delayFrameFuncs.length > 0)
			{
				_delayFrameFuncs.shift().call();
			}
			_cdGap.update(now);
			for each (var tempGap:TimeGapNode in _gaps) 
			{
				if (tempGap.update(now)) removeGap(tempGap.key);
			}
			for each (var tempUpdate:TimeUpdateNode  in _updateFuncs) 
			{
				if (tempUpdate.update(gap)) removeUpdate(tempUpdate.key);
			}
			for each (var tempPiece:TimePieceNode  in _timePieces) 
			{
				if (tempPiece.update(gap)) removeTimePiece(tempPiece.key);
			}
		}
		/**
		 * 添加延迟到下一帧处理函数
		 * @param	func
		 */
		public function delayFrame(func:Function):void 
		{
			_delayFrameFuncs.push(func);
		}
	}
}